/*
 *  Copyright (C) 2011 JiangHongTiao <jjurco.sk_gmail.com>
 * 
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 * 
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 * 
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package sk.lieskove301.jianghongtiao.liaad.prisoner.agent;

import java.util.Collection;
import java.util.Deque;
import sk.lieskove301.jianghongtiao.liaad.prisoner.gene.GeneticInfo;
import sk.lieskove301.jianghongtiao.liaad.prisoner.payoff.PayoffValue;
import sk.lieskove301.jianghongtiao.liaad.prisoner.memory.Forgetting;
import sk.lieskove301.jianghongtiao.liaad.prisoner.memory.ForgettingEnum;
import sk.lieskove301.jianghongtiao.liaad.prisoner.strategy.FightResultEnum;

/**
 * interface for agent. Encapsulate methods of agent that are required for the
 * game.
 * @author xjuraj
 */
public interface Agent {

    /**
     * get genetic information of his behavior. Genetic information is array of
     * length 5 with following meaning:
     * <ol>
     *    <li>first step of agent</li>
     *    <li>what to do when both of us cooperated</li>
     *    <li>what to do when I cooperated and partner betrayed</li>
     *    <li>what to do when I betrayed and partner cooperated</li>
     *    <li>what to do when both of us betrayed</li>
     * </ol>
     * @return Array of length 5 with genetic information
     */
    public GeneticInfo getGene();

    /**
     * Count cooperation of agent. Cooperation is based on agent's memory from 
     * previous fights, his genetic code and if he is optimistic/pessimistic or 
     * inverted/normal.
     * @param p make a fight with Agent p and return result
     * @param round number of actual round of fight
     * @return true,if agent decided to cooperate, false if agent is going to betray
     */
    public boolean cooperate(Agent p, int round);

    /**
     * set gene of agent. Gene is responsible for agent's behavior during the game.
     * Gene has the length 5 with following meaning:
     * <ol>
     *    <li>first step of agent</li>
     *    <li>what to do when both of us cooperated</li>
     *    <li>what to do when I cooperated and partner betrayed</li>
     *    <li>what to do when I betrayed and partner cooperated</li>
     *    <li>what to do when both of us betrayed</li>
     * </ol>
     * @param gene genetic information of agent
     */
    public void setGene(GeneticInfo gene);

    /**
     * remember the result of fight
     * @param fightWith with whom the agent was fighting
     * @param fightResult result of the fight 
     */
    public void setFightResults(Agent fightWith, FightResultEnum fightResult);

    /**
     * remove agents from memory if they are already dead
     * @param souls collection of dead agents
     */
    public void buryAgents(Collection deadSouls);
    
    /**
     * get total score of agent from all his games
     * @return total score of the agent
     */
    public double getScore();

    /**
     * clear agent's memories
     */
    public void amnesia();

    /**
     * clear agent's memory and also set agent's score to default (zero?) value
     */
    public void totalAmnesia();

    /**
     * get birth year of agent
     * @return year of born
     */
    public int getBirthday();

    /**
     * set birth year of agent
     * @param year year of born
     */
    public void setBirthday(int year);

    public int getBornYear();

    public void setBornYear(int bornYear);

    public ForgettingEnum getForgetting();

    public void setForgetting(ForgettingEnum forgetting);

    public PayoffValue getPayoff();

    public void setPayoff(PayoffValue payoff);
    
    public Agent copyAgent();

    public Deque<FightResultEnum> getMemory(Agent a);
    
    /**
     * agent can make inverted decisions. This can be useful with agents making
     * decision based on randomly generated number
     * @param inverted true if agent will make inverted decisions, false if not
     */
    public void setInvert(boolean inverted);
    
    /**
     * agent can make inverted decisions. This can be useful with agents making
     * decision based on randomly generated number
     * @return inverted true if agent will make inverted decisions, false if not
     */
    public boolean getInvert();
    
    /**
     * optimistic agent is agent which remember for cooperation and forget about
     * betray
     * @param optimistic true if agent is optimistic, false if agent is pessimistic
     */
    public void setOptimistic(boolean optimistic);
    
    /**
     * optimistic agent is agent which remember for cooperation and forget about
     * betray
     * @return optimistic true if agent is optimistic, false if agent is pessimistic
     */
    public boolean getOptimistic();

}
